﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace PubSubGeneric
{
    public class PublishingService : IPublishingService
    {
        public ISubscriptionCatalog SubscriptionCatalog
        {
            get;
            set;
        }

        public PublishingService()
            : this(PubSubManager.Catalog)
        {

        }

        public PublishingService(ISubscriptionCatalog subscriptionCatalog)
        {
            this.SubscriptionCatalog = subscriptionCatalog;
        }

        public void Publish<T>(string topic, T arg)
        {
            Trace.WriteLine("Publishing " + topic + " ,arg:" + arg.ToString());
            
            IEnumerable<ISubscriptionInfo<T>> matchedSubscriptions = this.SubscriptionCatalog.GetTopicSubscribers<T>(topic, arg);
            Trace.WriteLine("MatchedSubscriptions count:" + matchedSubscriptions.Count().ToString());
            
            foreach (var subscription in matchedSubscriptions)
            {
                PublishEventToSubscriberAsync<T>(topic, subscription, arg);
            }
        }

        private void PublishEventToSubscriberAsync<T>(string topic, ISubscriptionInfo<T> subscription, T arg)
        {
            new Task(new Action(() =>
            {
                try
                {
                    PublishEventToSubscriber(topic, subscription.Subscriber, arg);
                }
                catch (Exception ex)
                {
                    this.SubscriptionCatalog.Remove(topic, subscription);
                }
            })).Start();
        }

        private void PublishEventToSubscriber<T>(string topic, ISubscriber<T> subscriber, T arg)
        {

            subscriber.OnTopicPublished(topic, arg);

        }
    }
}
